﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Guedes_Library;
using System.Data;
using System.Configuration;
using System.Data.Objects.DataClasses;
using System.Linq.Expressions;

/// <summary>
/// Summary description for UsuarioModel
/// </summary>
public abstract class GuedesModel<T>
{
    public GuedesModel()
	{
		
	}

    /**
     * Persiste um entity de acordo com o entityKey e o objectContext
     * Caso seja um object novo, será adicionado ao object context e persistido em seguida
     * */
    public Boolean Save(T entity,
                            EntityKey key, guedesEntities context = null)
    {
        EntityObject ent = entity as EntityObject;

        using (guedesEntities updater = GetObjectContext(context))
        {
            try
            {
                T dbEntity = (T)updater.GetObjectByKey(key);
                DoChanges(dbEntity, entity);
           }
            catch (ObjectNotFoundException ex)
            {
                updater.AddObject(key.EntitySetName, entity);
            }
            catch (Exception ex)
            {
               return false;
            }
            updater.SaveChanges();
            return true;
        }

    }

    public Boolean Save(T entity, int id = 0)
    {
        if (id == null)
            id = 0;
        return Save(entity, GetEntityKey(id));
    }

    /** 
    *  Deleta um objeto persistente
    * */
    public Boolean Delete(EntityKey key, guedesEntities context = null)
    {
        using (guedesEntities updater = GetObjectContext(context))
        {
            try
            {
                T dbEntity = (T)updater.GetObjectByKey(key);
                updater.DeleteObject(dbEntity);
                updater.SaveChanges();
                return true;
            }
            catch {
                return false;
            }
        }
    }

    public Boolean Delete(int id)
    {
        return Delete(GetEntityKey(id));
    }


    public EntityKey GetEntityKey(int id)
    {
        return new EntityKey(GetTabela(), GetKeyTabela(), id);
    }

    /** 
    * Retorna um objeto que satisfaça a cláusula passada como parâmetro.
    * */
    public T SelectOne(Expression<Func<T, bool>> where)
    {
        using (guedesEntities db = GetObjectContext())
        {
            return db.CreateQuery<T>(GetTabela()).Where(where).FirstOrDefault();
        }
    }

    /**
     * Retorna todos os objetos persistentes
     * */
    public List<T> SelectAll()
    {
        using (guedesEntities db = GetObjectContext())
        {
            return db.CreateQuery<T>(GetTabela()).ToList();
        }
    }

    /**
     * Retorna o object context atual
     * */
    public  guedesEntities   GetObjectContext(guedesEntities context = null)
    {
        if (null != context && context.Connection.State ==
                  ConnectionState.Open) return context;

        return new guedesEntities(
          ConfigurationManager.ConnectionStrings[
          "guedesEntities"].ConnectionString);
    }

    /**
     * Retorna um objeto persistente de acordo com um entityKey para um respectivo object context 
     * */
    public object Get(EntityKey key,
                            guedesEntities context = null)
    {
        try
        {
            return (T)GetObjectContext(context).GetObjectByKey(key);
        }
        catch
        {
            return null;
        }
    }

    public T GetById(int id)
    {
        return (T)Get(GetEntityKey(id));
    }

    public abstract void DoChanges(T entity, T novo);
    public abstract string GetTabela();
    public abstract string GetKeyTabela();
}